package com.lhn.netty.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * base
 *
 * @author lhn
 * @date 2025/05/27 20:30
 * @since 1.0.0
 **/
public class NioServer {

    public static void main(String[] args) throws Exception{
        // 创建 serverSocketChannel - > ServerSocket
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 得到一个Selector对象
        Selector selector = Selector.open();
        // 绑定一个端口 6666
        serverSocketChannel.socket().bind(new InetSocketAddress(6666));
        // 设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        // 把 serverSocketChannel 注册到 selector 中, 关心事件为 OP_ACCEPT
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        // 循环等待客户端的连接
        System.out.println("注册后的 selectionKey " + selector.keys().size());
        while (true) {
            // 等待 1 秒
            if (selector.select(1000) == 0) { // 没有事件发生
                System.out.println("无连接");
                continue;
            }

            // 如果返回 > 0 获取到有事件的 SelectionKey
            Set <SelectionKey> selectionKeys = selector.selectedKeys();
            System.out.println("有 " + selectionKeys.size() + " 个事件发生");
            // 遍历 Set <SelectionKey>
            Iterator <SelectionKey> keyIterator = selectionKeys.iterator();
            while (keyIterator.hasNext()) {
                // 获取到 SelectionKey
                SelectionKey selectionKey = keyIterator.next();
                // 根据key 对应的事件处理
                if (selectionKey.isAcceptable()) {
                    // 生成一个 SocketChannel
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    // 设置非阻塞
                    socketChannel.configureBlocking(false);
                    System.out.println("客户端连接成功! 生成一个 socketChannel");
                    // 将 socketChannel 注册到 selector 同时关联一个 buffer
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                    System.out.println("客户端连接后 注册后的 selectionKey " + selector.keys().size());
                }
                if (selectionKey.isReadable()) { // 发生 op_read
                    // 通过key, 反向获取对应的 channel
                    SocketChannel channel = (SocketChannel) selectionKey.channel();
                    // 通过 channel 获取 buffer
                    ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();
                    channel.read(byteBuffer);
                    System.out.println("for comtmos" + ":" + new String(byteBuffer.array()));
                }
                // 手动从集合中移除 selectionKey, 防止重操作
                keyIterator.remove();
            }
        }
    }

}